/*
 * @Author: Mainul Islam
 */

package edu.uta.cse.randomgraph.graph;

import java.awt.Color;
import java.awt.Graphics;
import java.text.DecimalFormat;
import java.util.Random;

import edu.uta.cse.randomgraph.graph.property.Node;
import edu.uta.cse.randomgraph.util.DirUtil;
import edu.uta.cse.randomgraph.util.LogType;
import edu.uta.cse.randomgraph.util.LogWriter;
import edu.uta.cse.randomgraph.util.MyDrawUtil;


public class ErdosRenyiGraph extends MyGraph {

	private double conProb;
	private static String folderName = "ErdosRenyi";

	
	public ErdosRenyiGraph(int nodeNum) {
		super(nodeNum);
		conProb = 0.0;
	}
	
	public ErdosRenyiGraph(int nodeNum, double onnectionProbability) {
		super(nodeNum);
		conProb = onnectionProbability;
	}

	public double getConnectionProbability() {
		return this.conProb;
	}
	
	private void initPreCompute() {
		initDist();
	}
	
	private void preCompute() {
		computeFloydWarshal();
		computeDegreeList();
	}

	
	public void generateGraph() {
		initPreCompute();
		
		int i;
		for (i=0; i<numNodes; i++)
			nodes[i] = new Node();

		Random rand = new Random();
		numEdges = 0;
		for (i=0; i<numNodes-1; i++) {
			for (int j=i+1; j<numNodes; j++) {
				if ( conProb >= rand.nextDouble() ) {
					numEdges++;
					edgeMat[i][j] = edgeMat[j][i] = true;
					dist[i][j] = dist[j][i] = 1;
					nodes[i].deg++;
					nodes[j].deg++;
					nodes[i].edgeList.add(j);
					nodes[j].edgeList.add(i);
				}
			}
		}
		
		preCompute();
	}
	

	public void drawGraph(int currWidth, int currHeight, Graphics g) {
		
		if(isHeightWidthChanged(currWidth, currHeight) || !this.isCoordinatesGenerated) {
			MyDrawUtil.generateCoordinatesForNodes(currWidth, currHeight, nodes, numNodes);
			isCoordinatesGenerated = true;
		}
		
		if(this.drawConComp)
			computeConnectedComponents();
		
		Color c;
		c = Color.RED;
		for (int i=0; i<numNodes; i++)	{
			if(nodes[i].isDeleted)
				continue;
			if(this.drawConComp)
				c = MyDrawUtil.assignColor(nodes[i].getConCompRank());
			MyDrawUtil.drawNode(nodes[i].X, nodes[i].Y, nodeDiam, c, g);
		}
		
		c = Color.BLACK;
		for (int i=0; i<numNodes-1; i++) {
			if(nodes[i].isDeleted)
				continue;
			for (int j=i+1; j<numNodes; j++) {
				if ( edgeMat[i][j] ) {
					if(this.drawConComp)
						c = MyDrawUtil.assignColor(nodes[i].getConCompRank());
					MyDrawUtil.drawEdge(nodes[i], nodes[j], nodeRad, c, g);
				}
			}
		}
		
	}
	
	public void writeInfo(LogWriter lw, LogType lt) {
		String dirName, fileName;
		
		dirName = lw.outputDirectory + folderName;
		if( !lw.createDirectory(dirName) )
			return;
		
		fileName = dirName + "/" + lw.getLogTypeFileName(lt);		

		if(lt == LogType.DegreeDistribution || lt == LogType.AgeDegreeRelation) {
				switch(lt) {
					case AgeDegreeRelation:		
						dirName  = dirName + "/" + lw.ageDegreeRelationFolderName;		break;
					case DegreeDistribution:
						dirName  = dirName + "/" + lw.degDistFolderName;		break;
				}
				
				if( !lw.createDirectory(dirName) )
					return;
				int ind = DirUtil.getLastFileNameIndexInDirectory(dirName);
				fileName = dirName + "/" + Integer.toString(ind+1) + ".txt";
		}

		if(!lw.openWriter(fileName))
			return;

		switch(lt) {
			case Summary:				writeSummary(lw);				break;
			case AgeDegreeRelation:		writeAgeDegreeRelation(lw);		break;
			case DegreeDistribution:	writeDegreeDistribution(lw);	break;
		}
		
		lw.closeWriter();
	}

	private void writeSummary(LogWriter lw) {
		DecimalFormat df = new DecimalFormat("#.########");
		
		double avgDeg = 0.0;
		if (numNodes != 0) 
			avgDeg = (double)(numEdges*2)/(double)numNodes;

		lw.write( String.format("%10s", numNodes) );
		lw.write( String.format("%10s", df.format(conProb)) );
		lw.write( String.format("%10s", numEdges) );
		lw.write( String.format("%10s", diameter) );
		lw.write( String.format("%10s", numConComp) );
		lw.write( String.format("%10s", maxSizeConComp) );
		lw.write( String.format("%16s", df.format(avgClusCo)) );
		lw.write( String.format("%16s", df.format(avgDeg)) );
		lw.writeLine();
	}

}
